/**
 * @file LyricUi.cpp
 * @brief 歌词显示UI实现
 * @details 实现歌词的界面展示、滚动同步和用户交互处理
 */
#include <cstddef>
#include <iostream>
#include <fstream>
#include <sstream>
#include <cmath>
#include <locale>
#include "LyricUi.h"
#include "kugou.h"
#include "config_dialog.h"
#include "lyric_log.h"

// 声明全局LyricWidget实例（定义在plugin.cpp中）
extern LyricWidget* g_lyric_widget;

// 获取全局计数器
gint get_current_sequence() {
	g_assert(g_lyric_widget != NULL);
	return (gint)g_atomic_int_get((gint*)&g_lyric_widget->global_sequence);
}

gint get_next_sequence(void)
{
    g_assert(g_lyric_widget != NULL);
	g_atomic_int_inc((gint*)&g_lyric_widget->global_sequence);
    return (gint)g_atomic_int_get((gint*)&g_lyric_widget->global_sequence);
}

// 文本标签定义
static GtkTextTag *tagItalic;
static GtkTextTag *tagBold;
static GtkTextTag *tagLarge;
static GtkTextTag *tagCenter;
static GtkTextTag *tagSmall;
static GtkTextTag *tagForegroundColorHighlight;
static GtkTextTag *tagForegroundColorRegular;
static GtkTextTag *tagForegroundColorGrayscale;
static GtkTextTag *tagLeftmargin;
static GtkTextTag *tagRightmargin;
static GtkTextTag *tagRegular;

// 标签组定义
static GList *tagsTitle;
static GList *tagsArtist;
static GList *tagsHighlightLine;
static GList *tagsRegularLine;
static GList *tagsGrayscaleLine;
static GList *tagPadding;

/**
 * @brief 初始化文本标签样式
 * @param refBuffer 文本缓冲区
 * @param fontscale 字体缩放比例，默认为中等大小
 * @param margin 边距，默认为22像素
 * @param bold 是否使用粗体，默认为1（使用）
 * @param align 文本对齐方式，默认为居中
 * @param highlightcolor 高亮文本颜色，默认为"#571c1c"
 * @param regularcolor 普通文本颜色，默认为"#000000"
 * @param graycolor 灰色文本颜色，默认为"#585858"
 */
void init_tags(GtkTextBuffer* refBuffer, double fontscale = PANGO_SCALE_MEDIUM, int margin = 22, int bold = 1, GtkJustification align = GTK_JUSTIFY_CENTER,
               const gchar* highlightcolor = "#571c1c", const gchar* regularcolor = "#000000", const gchar* graycolor="#585858") {
    // 创建各种文本样式标签
    tagItalic = gtk_text_buffer_create_tag(refBuffer, "italic", "style", PANGO_STYLE_ITALIC, "scale", fontscale, NULL);
    tagRegular = gtk_text_buffer_create_tag(refBuffer, "regular", "weight", PANGO_WEIGHT_NORMAL, "scale", fontscale, NULL);
    tagLeftmargin = gtk_text_buffer_create_tag(refBuffer, "leftmargin", "left-margin", (int)(margin * fontscale), NULL);
    tagRightmargin = gtk_text_buffer_create_tag(refBuffer, "rightmargin", "right-margin", (int)(margin * fontscale), NULL);

    tagBold = gtk_text_buffer_create_tag(refBuffer, "bold", "weight", PANGO_WEIGHT_BOLD, "scale", fontscale, NULL);
    tagLarge = gtk_text_buffer_create_tag(refBuffer, "large", "scale", 1.2 * fontscale, NULL);
    tagSmall = gtk_text_buffer_create_tag(refBuffer, "small", "scale", 0.0001, NULL);
    tagCenter = gtk_text_buffer_create_tag(refBuffer, "center", "justification", GTK_JUSTIFY_CENTER, NULL);

    tagForegroundColorHighlight = gtk_text_buffer_create_tag(refBuffer, "color_highlight", "foreground", highlightcolor, NULL);
    tagForegroundColorRegular = gtk_text_buffer_create_tag(refBuffer, "color_regular", "foreground", regularcolor, NULL);
    tagForegroundColorGrayscale = gtk_text_buffer_create_tag(refBuffer, "color_gray", "foreground", graycolor, NULL);

    tagsTitle = g_list_append(NULL, tagLarge);
    tagsTitle = g_list_append(tagsTitle, tagForegroundColorRegular);
    tagsTitle = g_list_append(tagsTitle, tagBold);
    tagsTitle = g_list_append(tagsTitle, tagCenter);

    tagsArtist = g_list_append(NULL, tagItalic);
    tagsArtist = g_list_append(tagsArtist, tagForegroundColorRegular);
    tagsArtist = g_list_append(tagsArtist, tagCenter);

    
    if (bold == 1) {
        tagsHighlightLine = g_list_append(NULL, tagBold);
    }
    else {
        tagsHighlightLine = g_list_append(NULL, tagRegular);
    }
    tagsHighlightLine = g_list_append(tagsHighlightLine, tagForegroundColorHighlight);

    tagsRegularLine = g_list_append(NULL, tagRegular);
    tagsRegularLine = g_list_append(tagsRegularLine, tagForegroundColorRegular);

    tagsGrayscaleLine = g_list_append(NULL, tagRegular);
    tagsGrayscaleLine = g_list_append(tagsGrayscaleLine, tagForegroundColorGrayscale);


    if (align == GTK_JUSTIFY_LEFT) {
        tagsRegularLine = g_list_append(tagsRegularLine, tagLeftmargin);
        tagsHighlightLine = g_list_append(tagsHighlightLine, tagLeftmargin);
        tagsGrayscaleLine = g_list_append(tagsGrayscaleLine, tagLeftmargin);
    }
    if (align == GTK_JUSTIFY_CENTER) {
        tagsRegularLine = g_list_append(tagsRegularLine, tagCenter);
        tagsHighlightLine = g_list_append(tagsHighlightLine, tagCenter);
        tagsGrayscaleLine = g_list_append(tagsGrayscaleLine, tagCenter);
    }
    if (align == GTK_JUSTIFY_RIGHT) {
        tagsRegularLine = g_list_append(tagsRegularLine, tagRightmargin);
        tagsHighlightLine = g_list_append(tagsHighlightLine, tagRightmargin);
        tagsGrayscaleLine = g_list_append(tagsGrayscaleLine, tagRightmargin);
    }

    tagPadding = g_list_append(NULL, tagSmall);
}

/**
 * @brief 对文本行应用指定的标签组
 * @param buffer 文本缓冲区
 * @param line_start 文本行起始迭代器
 * @param line_end 文本行结束迭代器
 * @param tags 要应用的标签组
 */
void apply_line_with_tags(GtkTextBuffer* buffer, GtkTextIter* line_start, GtkTextIter* line_end, GList* tags)
{
    for (GList* l = tags; l; l = l->next) {
        GtkTextTag* tag = (GtkTextTag*)l->data;
        gtk_text_buffer_apply_tag(buffer, tag, line_start, line_end);
    }
}

/**
 * @brief 从文本行移除指定的标签组
 * @param buffer 文本缓冲区
 * @param line_start 文本行起始迭代器
 * @param line_end 文本行结束迭代器
 * @param tags 要移除的标签组
 */
void remove_line_with_tags(GtkTextBuffer* buffer, GtkTextIter* line_start, GtkTextIter* line_end, GList* tags)
{
    for (GList* l = tags; l; l = l->next) {
        GtkTextTag* tag = (GtkTextTag*)l->data;
        gchar* name = NULL;
        g_object_get(G_OBJECT(tag), "name", &name, NULL);
        gtk_text_buffer_remove_tag_by_name(buffer, name, line_start, line_end);
    }
}

/****************************************************************************************/

/**
 * @brief 获取文本视图中可见的行数
 * @param text_view GTK文本视图对象
 * @param pixels_above 行上方留出的像素数
 * @param pixels_below 行下方留出的像素数
 * @return 可见行数
 */
int get_visible_line_count(GtkTextView* text_view, gint pixels_above, gint pixels_below) {
    // 获取文本缓冲区
    GtkTextBuffer* buffer = gtk_text_view_get_buffer(text_view);
    GtkTextIter iter;
    gtk_text_buffer_get_start_iter(buffer, &iter);

    // 获取TextView可见区域高度
    GdkRectangle visible_rect;
    gtk_text_view_get_visible_rect(text_view, &visible_rect);

    // 获取单行高度
    PangoContext* context = gtk_widget_get_pango_context(GTK_WIDGET(text_view));
    PangoLayout* layout = pango_layout_new(context);
    pango_layout_set_text(layout, "示例", -1); // 用任意一行歌词的字体
    int width, height;
    pango_layout_get_pixel_size(layout, &width, &height);
    g_object_unref(layout);

    if (height == 0) height = 12; // 防止除0

    // 计算可见行数
    int n = visible_rect.height / (height + pixels_above + pixels_below);
    if (n < 1) n = 1;
    return n;
}

/**
 * @brief 确保指定迭代器位置的文本在视图中居中显示
 * @param text_view GTK文本视图对象
 * @param iter 文本迭代器，指向要居中显示的文本位置
 */
void ensure_centered(GtkTextView* text_view, GtkTextIter* iter) {
    // 第一次尝试快速滚动
    gtk_text_view_scroll_to_iter(text_view, iter, 0.0, FALSE, 0.5, 0.0);

    // 获取精确位置并调整
    GdkRectangle location;
    gtk_text_view_get_iter_location(text_view, iter, &location);

    GtkAllocation allocation;
    gtk_widget_get_allocation(GTK_WIDGET(text_view), &allocation);

    // 计算理想的垂直位置
    int desired_y = location.y - (allocation.height / 2) + (location.height / 2);
    GtkAdjustment* adj = gtk_scrollable_get_vadjustment(GTK_SCROLLABLE(text_view));
    gtk_adjustment_set_value(adj, desired_y);
}

/********************************************/

/**
 * @brief 创建并初始化一个新的歌词显示组件
 * @return 初始化后的LyricWidget对象指针
 */
LyricWidget* lyric_widget_new()
{

    LyricWidget* widget = g_new0(LyricWidget, 1);
    g_mutex_init(&widget->mutex);
    //GtkWidget* vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);

    //widget->title_label = gtk_label_new(NULL);
    //gtk_label_set_justify(GTK_LABEL(widget->title_label), GTK_JUSTIFY_CENTER);
    //gtk_box_pack_start(GTK_BOX(vbox), widget->title_label, FALSE, FALSE, 0);

    widget->lyric_view = gtk_text_view_new();
    widget->lyric_buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(widget->lyric_view));
    gtk_text_view_set_editable(GTK_TEXT_VIEW(widget->lyric_view), FALSE);
    gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(widget->lyric_view), FALSE);
    // 禁用焦点，防止文本选择导致的问题
    gtk_widget_set_can_focus(widget->lyric_view, FALSE);
    
    // 注意：GTK3 没有 gtk_text_view_set_selectable 函数
    // 通过禁用焦点和事件处理来防止文本选择
    
    init_tags(widget->lyric_buffer);

    widget->lyric_container = gtk_scrolled_window_new(NULL, NULL);
    // 设置滚动窗口策略，确保内容可见
    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(widget->lyric_container), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
    gtk_container_add(GTK_CONTAINER(widget->lyric_container), widget->lyric_view);

    // 添加边框样式（颜色170, 170, 170即#AAAAAA）
    GtkCssProvider *css_provider = gtk_css_provider_new();
    gtk_css_provider_load_from_data(css_provider,
        "scrolledwindow { "
        "   border: 1px solid #AAAAAA; "
        "} ", -1, NULL);
    GtkStyleContext *context = gtk_widget_get_style_context(widget->lyric_container);
    gtk_style_context_add_provider(context, GTK_STYLE_PROVIDER(css_provider),
                                   GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
    g_object_unref(css_provider);

    // 初始化字符串数组为空字符串
    widget->title[0] = '\0';
    widget->artist[0] = '\0';
    widget->location[0] = '\0';

    //g_object_set_data(G_OBJECT(vbox), "lyric-continer", scroll);
    return widget;
}

/**
 * @brief 释放歌词行链表资源
 * @param pplines 指向歌词行链表的指针
 */
void free_lines(GList** pplines)
{
    if (!pplines || !*pplines) {
        return;
    }
    free_lyrics_list(*pplines);
    *pplines = NULL;
}

gpointer LyricLine_copy (gconstpointer src, gpointer user_data)
{
    const LyricLine *p_src = (LyricLine *)src;
    LyricLine *p_new = g_slice_new0(LyricLine);  // 使用g_slice_new0分配内存，与释放方式匹配

    if (p_src->text)
        p_new->text = g_strdup (p_src->text);
    else
        p_new->text = NULL;
    p_new->timestamp = p_src->timestamp;
    p_new->start_offset = p_src->start_offset;
    p_new->end_offset = p_src->end_offset;

    return (gpointer)p_new;
}

/**
 * @brief 拷贝歌词行列表资源
 * @param plines 歌词行列表指针的指针
 */
GList* copy_lines(GList* plines)
{
    if (!plines) {
        return NULL;
    }
    GList *list_copy = g_list_copy_deep(plines, LyricLine_copy, NULL);
    return list_copy;
}

/**
 * @brief 清空歌词组件的所有数据和状态
 * @param widget LyricWidget对象指针
 */
void clear_widget(LyricWidget* widget)
{
    g_assert(widget != NULL);
    
    g_mutex_lock(&widget->mutex);
    
    // 先停止定时器（防止 update_lyrics 继续运行）
    if (widget->timer_id > 0) {
        g_source_remove(widget->timer_id);
        widget->timer_id = 0;
    }
    
    // 重置所有状态（必须在清空缓冲区之前）
    widget->current_line = -1;
    widget->past_line = NULL;
    
    // 释放歌词列表
    if (widget->lyrics) {
        free_lyrics_list(widget->lyrics);
        widget->lyrics = NULL;
    }

    // 重置字符串数组为空字符串（不再需要g_free）
    widget->title[0] = '\0';
    widget->artist[0] = '\0';
    widget->location[0] = '\0';

    g_mutex_unlock(&widget->mutex);
}

/**
 * @brief 释放SetLyricsUIData结构体中的资源
 * @param data SetLyricsUIData结构体指针
 */
void free_set_lyrics_ui_data(SetLyricsUIData* data) {
    if (data) {
        // 释放lyrics_temp链表
        if (data->lyrics_temp) {
            free_lyrics_list(data->lyrics_temp);
            data->lyrics_temp = NULL;
        }
        // 释放SetLyricsUIData结构体本身
        g_free(data);
    }
}

/**
 * @brief 初始化歌词显示处理函数
 * @param data LyricWidget对象指针
 * @return 返回false以停止定时器（只执行一次）
 */
gboolean init_lyric_handle(gpointer data)
{
    SetLyricsUIData* loading_data = (SetLyricsUIData*)data;
    g_assert(loading_data != NULL);
    g_assert(loading_data->widget != NULL);
    
    LyricWidget* widget = loading_data->widget;
    gint song_seq = loading_data->song_seq;
    GList* lyrics_temp = loading_data->lyrics_temp;
    
    lyric_log_info("init_lyric_handle");

    // 检查是否已经切歌（通过比较计数器），在clear_widget之前检查
    guint current_sequence = get_current_sequence();
    if (song_seq != current_sequence) {
        lyric_log_warning("init_lyric_handle: song changed (saved=%u, current=%u), discarding lyrics", 
                         song_seq, current_sequence);
        // 释放加载数据
        free_set_lyrics_ui_data(loading_data);
        return G_SOURCE_REMOVE;
    }

    clear_widget(widget);
    // 保护共享数据访问
    g_mutex_lock(&widget->mutex);
    g_strlcpy(widget->title, loading_data->title, sizeof(widget->title));
    g_strlcpy(widget->artist, loading_data->artist, sizeof(widget->artist));
    g_strlcpy(widget->location, loading_data->location, sizeof(widget->location));
    if (lyrics_temp) {
        widget->lyrics = copy_lines(lyrics_temp);
        lyric_log_info("init_lyric_handle: transferred lyrics_temp to lyrics");
    }
    const gchar* safe_title = widget->title[0] != '\0' ? widget->title : "";
    const gchar* safe_artist = widget->artist[0] != '\0' ? widget->artist : "";
    g_mutex_unlock(&widget->mutex);
    
    // // 再次检查是否已经切歌（通过比较计数器），在初始化歌词之前再次检查
    // current_sequence = get_current_sequence();
    // if (song_seq != current_sequence) {
    //     lyric_log_warning("init_lyric_handle: song changed (saved=%u, current=%u), discarding lyrics", 
    //                      song_seq, current_sequence);
    //     // 释放加载数据
    //     free_set_lyrics_ui_data(loading_data);
    //     return G_SOURCE_REMOVE;
    // }
    
    lyric_log_info("init_lyric_handle: lyrics_temp count: %d", lyrics_temp ? g_list_length(lyrics_temp) : 0);
    
    // 重新获取mutex设置lyrics
    g_mutex_lock(&widget->mutex);
    lyric_log_info("init_lyric_handle: final lyrics count: %d", widget->lyrics ? g_list_length(widget->lyrics) : 0);
    init_lyric(widget, safe_title, safe_artist, widget->lyrics);
    // 释放仅拷贝的链表节点，避免后续再次释放数据
    g_mutex_unlock(&widget->mutex);

    // 启动定时器
    start_time(widget);
    lyric_log_info("init_lyric_handle: timer started");
    
    // 释放加载数据
    free_set_lyrics_ui_data(loading_data);
#ifdef _WIN32
    GMainContext* main_context = g_main_context_default();
    if (main_context) {
        g_main_context_wakeup(main_context);
        lyric_log_debug("main context woken up");
    }
#endif
    lyric_log_info("init_lyric_handle: completed");
    return G_SOURCE_REMOVE;  // 返回 FALSE 以停止超时定时器，只执行一次
}

/**
 * @brief 初始化歌词显示内容
 * @param widget LyricWidget对象指针
 * @param title 歌曲标题
 * @param artist 歌手名称
 * @param lines 歌词行链表
 */
void init_lyric(LyricWidget* widget, const gchar* title, const gchar* artist, GList* lines)
{
    g_assert(widget != NULL);
    if (!widget->lyric_view || !GTK_IS_WIDGET(widget->lyric_view) || !widget->lyric_buffer) {
        lyric_log_error("init_lyric: invalid lyric_view/buffer");
        return;
    }

    // // 等待一小段时间，确保所有 GTK 操作完成
	// while (gtk_events_pending()) {
	// 	gtk_main_iteration();
	// }


    lyric_log_info("init_lyric ...");
    lyric_log_info("init_lyric title: %s", title ? title : "(null)");
    lyric_log_info("init_lyric artist: %s", artist ? artist : "(null)");
    lyric_log_info("init_lyric lines count: %d", lines ? g_list_length(lines) : 0);

	// 清空歌词
    GtkTextIter start, end;
    gtk_text_buffer_get_start_iter(widget->lyric_buffer, &start);
    gtk_text_buffer_get_end_iter(widget->lyric_buffer, &end);
    gtk_text_buffer_delete(widget->lyric_buffer, &start, &end);

    // 计算可见行数和中间行位置
    gint above = gtk_text_view_get_pixels_above_lines(GTK_TEXT_VIEW(widget->lyric_view));
    gint below = gtk_text_view_get_pixels_below_lines(GTK_TEXT_VIEW(widget->lyric_view));
    int n = get_visible_line_count(GTK_TEXT_VIEW(widget->lyric_view), above, below);
    int middle_line = (int)round(n / 2.0f);


    // 在中间行上方插入空行，使得当前歌词行居中显示
    GtkTextIter iter;
    gtk_text_buffer_get_end_iter(widget->lyric_buffer, &iter);
    for (int i = 0;i < middle_line - 1;i++) {
        gtk_text_buffer_insert_with_tags(widget->lyric_buffer, &iter, "\n", -1, tagRegular, tagForegroundColorRegular, NULL);
    }
    gtk_text_buffer_insert(widget->lyric_buffer, &iter, "\n", -1);

	// 插入标题和艺术家信息
    if (title) {
        gtk_text_buffer_insert_with_tags(widget->lyric_buffer, &iter, title, -1, tagBold, tagLarge, tagCenter, NULL);
    }
    gtk_text_buffer_insert(widget->lyric_buffer, &iter, "\n", -1);
    if (artist) {
        gtk_text_buffer_insert_with_tags(widget->lyric_buffer, &iter, artist, -1, tagBold, tagCenter, tagItalic, NULL);
    }
    gtk_text_buffer_insert(widget->lyric_buffer, &iter, "\n", -1);

	// 插入歌词内容并记录偏移量
    int lyric_count = 0;
    for (GList* l = lines; l; l = l->next) {
        LyricLine* line = (LyricLine*)l->data;
        // 检查line和line->text是否有效
        if (!line || !line->text) {
            continue;
        }
        gtk_text_buffer_get_end_iter(widget->lyric_buffer, &iter);
        line->start_offset = gtk_text_iter_get_offset(&iter);
        gtk_text_buffer_insert_with_tags(widget->lyric_buffer, &iter, line->text, -1, tagRegular, tagCenter, tagForegroundColorRegular, NULL);
        line->end_offset = gtk_text_iter_get_offset(&iter);  // 存储偏移量
        gtk_text_buffer_insert(widget->lyric_buffer, &iter, "\n", -1);
        lyric_count++;
    }
    lyric_log_info("init_lyric: inserted %d lyric lines", lyric_count);

    // 在歌词下方插入空行
    for (int i = 0;i < middle_line;i++) {
        gtk_text_buffer_insert_with_tags(widget->lyric_buffer, &iter, "\n", -1, tagRegular, tagCenter, tagForegroundColorRegular, NULL);
    }

    lyric_log_info("init_lyric end .");
}

/**
 * @brief 根据当前播放时间更新歌词显示
 * @param widget LyricWidget对象指针
 * @param current_time_ms 当前播放时间（毫秒）
 */
void update_lyrics(LyricWidget* widget, gdouble current_time_ms) {
    g_assert(widget != NULL);
    g_assert(widget->lyric_buffer != NULL);
    
    int i = 0;

    g_mutex_lock(&widget->mutex);

    // 检查歌词列表是否为空
    if (!widget->lyrics) {
        g_mutex_unlock(&widget->mutex);
        return;
    }
    
    // 获取缓冲区当前大小，确保偏移量有效
    GtkTextIter buffer_start, buffer_end;
    gtk_text_buffer_get_bounds(widget->lyric_buffer, &buffer_start, &buffer_end);
    gint buffer_size = gtk_text_iter_get_offset(&buffer_end);
    
    gint count = g_list_length(widget->lyrics);
    if (widget->current_line == count) {
        g_mutex_unlock(&widget->mutex);
        return;
    }

    // 遍历所有歌词行，更新样式和当前行
    int new_current_line = -1;
    LyricLine* new_past_line = NULL;
    
    for (GList* l = widget->lyrics; l; l = l->next, ++i) {
        LyricLine* line = (LyricLine*)l->data;
        
        // 检查line是否有效
        if (!line) {
            continue;
        }

        if (current_time_ms >= line->timestamp) {
            // 已过时或正在唱的行
            // 保存当前应该高亮的行（最后一个时间戳<=当前时间的行）
            new_current_line = i;
            new_past_line = line;
        }
    }
    
    // 如果没找到任何匹配的行（所有时间戳都大于当前时间），使用第一行
    if (new_current_line == -1) {
        new_current_line = 0;
        if (widget->lyrics) {
            new_past_line = (LyricLine*)widget->lyrics->data;
        }
    }
    
    // 如果当前行改变了，更新高亮
    if (widget->current_line != new_current_line && new_past_line) {
        // 检查new_past_line是否有效
        if (!new_past_line) {
            g_mutex_unlock(&widget->mutex);
            return;
        }
        
        // 清除之前的高亮
        if (widget->past_line) {
            // 检查偏移量是否在缓冲区有效范围内
            if (widget->past_line->start_offset >= 0 && widget->past_line->end_offset >= 0 &&
                widget->past_line->start_offset < buffer_size && widget->past_line->end_offset <= buffer_size) {
                GtkTextIter line_start, line_end;
                gtk_text_buffer_get_iter_at_offset(widget->lyric_buffer, &line_start, widget->past_line->start_offset);
                gtk_text_buffer_get_iter_at_offset(widget->lyric_buffer, &line_end, widget->past_line->end_offset);
                // 再次验证迭代器是否有效
                if (gtk_text_iter_get_offset(&line_start) >= 0 && gtk_text_iter_get_offset(&line_end) >= 0) {
                    remove_line_with_tags(widget->lyric_buffer, &line_start, &line_end, tagsHighlightLine);
                    apply_line_with_tags(widget->lyric_buffer, &line_start, &line_end, tagsGrayscaleLine);
                }
            }
        }
        
        // 高亮新行
        widget->current_line = new_current_line;
        widget->past_line = new_past_line;
        
        // 检查新行的偏移量是否在缓冲区有效范围内
        if (new_past_line->start_offset >= 0 && new_past_line->end_offset >= 0 &&
            new_past_line->start_offset < buffer_size && new_past_line->end_offset <= buffer_size) {
            GtkTextIter line_start, line_end;
            gtk_text_buffer_get_iter_at_offset(widget->lyric_buffer, &line_start, new_past_line->start_offset);
            gtk_text_buffer_get_iter_at_offset(widget->lyric_buffer, &line_end, new_past_line->end_offset);
            
            // 再次验证迭代器是否有效
            if (gtk_text_iter_get_offset(&line_start) >= 0 && gtk_text_iter_get_offset(&line_end) >= 0) {
                // 先移除可能存在的灰色和常规标签
                remove_line_with_tags(widget->lyric_buffer, &line_start, &line_end, tagsGrayscaleLine);
                remove_line_with_tags(widget->lyric_buffer, &line_start, &line_end, tagsRegularLine);
                apply_line_with_tags(widget->lyric_buffer, &line_start, &line_end, tagsHighlightLine);
            }
        }
    }
    
    // 遍历所有行，更新其他行的样式
    i = 0;
    for (GList* l = widget->lyrics; l; l = l->next, ++i) {
        LyricLine* line = (LyricLine*)l->data;
        
        // 检查line是否有效
        if (!line) {
            continue;
        }
        
        // 跳过正在高亮的行
        if (i == widget->current_line) {
            continue;
        }
        
        // 检查偏移量是否在缓冲区有效范围内
        if (line->start_offset < 0 || line->end_offset < 0 ||
            line->start_offset >= buffer_size || line->end_offset > buffer_size) {
            // 偏移量无效，跳过这一行（可能是缓冲区已被清空）
            continue;
        }
        
        if (current_time_ms > line->timestamp) {
            // 已过时的行，标记为灰色
            GtkTextIter line_start, line_end;
            gtk_text_buffer_get_iter_at_offset(widget->lyric_buffer, &line_start, line->start_offset);
            gtk_text_buffer_get_iter_at_offset(widget->lyric_buffer, &line_end, line->end_offset);
            // 再次验证迭代器是否有效
            if (gtk_text_iter_get_offset(&line_start) >= 0 && gtk_text_iter_get_offset(&line_end) >= 0) {
                remove_line_with_tags(widget->lyric_buffer, &line_start, &line_end, tagsHighlightLine);
                remove_line_with_tags(widget->lyric_buffer, &line_start, &line_end, tagsRegularLine);
                apply_line_with_tags(widget->lyric_buffer, &line_start, &line_end, tagsGrayscaleLine);
            }
        } else {
            // 未来的行，标记为常规（黑色）
            GtkTextIter line_start, line_end;
            gtk_text_buffer_get_iter_at_offset(widget->lyric_buffer, &line_start, line->start_offset);
            gtk_text_buffer_get_iter_at_offset(widget->lyric_buffer, &line_end, line->end_offset);
            // 再次验证迭代器是否有效
            if (gtk_text_iter_get_offset(&line_start) >= 0 && gtk_text_iter_get_offset(&line_end) >= 0) {
                remove_line_with_tags(widget->lyric_buffer, &line_start, &line_end, tagsHighlightLine);
                remove_line_with_tags(widget->lyric_buffer, &line_start, &line_end, tagsGrayscaleLine);
                apply_line_with_tags(widget->lyric_buffer, &line_start, &line_end, tagsRegularLine);
            }
        }
    }

    // 如果存在上一行，滚动到该行
    if (widget->past_line) {
        // 检查偏移量是否在缓冲区有效范围内
        int offset = widget->past_line->start_offset;
        if (offset >= 0 && offset < buffer_size) {
            GtkTextIter line_start;
            gtk_text_buffer_get_iter_at_offset(widget->lyric_buffer, &line_start, offset);
            // 再次验证迭代器是否有效
            if (gtk_text_iter_get_offset(&line_start) >= 0) {
                ensure_centered(GTK_TEXT_VIEW(widget->lyric_view), &line_start);
            }
        }
    }

    g_mutex_unlock(&widget->mutex);
}

/**
 * @brief "设置"菜单项的点击回调函数
 * @param item 被点击的菜单项
 * @param user_data 用户数据（通常是父窗口指针）
 */
void on_settings_activate(GtkMenuItem* item, gpointer user_data) {
    // 创建并显示设置对话框
    GtkWidget* dialog = gtk_message_dialog_new(
        GTK_WINDOW(user_data),  // 父窗口
        GTK_DIALOG_MODAL,       // 模态对话框
        GTK_MESSAGE_INFO,
        GTK_BUTTONS_OK,
        "打开设置窗口"
    );
    gtk_dialog_run(GTK_DIALOG(dialog));
    gtk_widget_destroy(dialog);
}

/**
 * @brief "搜索"菜单项的点击回调函数
 * @param item 被点击的菜单项
 * @param user_data 用户数据（通常是父窗口指针）
 */
void on_search_activate(GtkMenuItem* item, gpointer user_data) {
    GtkWidget* dialog = gtk_message_dialog_new(
        GTK_WINDOW(user_data),
        GTK_DIALOG_MODAL,
        GTK_MESSAGE_INFO,
        GTK_BUTTONS_OK,
        "打开搜索框"
    );
    gtk_dialog_run(GTK_DIALOG(dialog));
    gtk_widget_destroy(dialog);
}

// 菜单项点击回调：编辑
void on_edit_activate(GtkMenuItem* item, gpointer user_data) {
    GtkWidget* dialog = gtk_message_dialog_new(
        GTK_WINDOW(user_data),
        GTK_DIALOG_MODAL,
        GTK_MESSAGE_INFO,
        GTK_BUTTONS_OK,
        "进入编辑模式"
    );
    gtk_dialog_run(GTK_DIALOG(dialog));
    gtk_widget_destroy(dialog);
}

// 处理按钮按下事件，防止双击崩溃
gboolean on_button_press_event(GtkWidget* widget, GdkEventButton* event, gpointer user_data) {
    LyricWidget* lyric_widget = (LyricWidget*)user_data;
    
    g_assert(lyric_widget != NULL);
    
    // 双击事件（button 1 = 左键）
    if (event->type == GDK_2BUTTON_PRESS && event->button == 1) {
        lyric_log_debug("on_button_press_event: double click detected");
        
        // 防止默认的文本选择行为导致崩溃
        // 由于我们已经禁用了文本选择，这里主要是记录日志
        // 如果需要实现双击功能，可以在这里添加
        
        return TRUE; // 阻止事件继续传播
    }
    
    // 其他按钮事件继续传播
    return FALSE;
}

// 拦截默认右键菜单并添加自定义项
void on_populate_popup(GtkTextView* text_view, GtkMenu* menu, gpointer user_data) {
    if (!text_view || !menu || !user_data) {
        lyric_log_error("on_populate_popup: invalid parameters");
        return;
    }
    
    LyricWidget* lyric_widget = (LyricWidget*)user_data;
    g_assert(lyric_widget != NULL);
    
    // 可选：移除默认菜单项（若需保留默认菜单，注释此段）
    GList* children = gtk_container_get_children(GTK_CONTAINER(menu));
    while (children != NULL) {
        GtkWidget* child = GTK_WIDGET(children->data);
        if (child && GTK_IS_WIDGET(child)) {
            gtk_container_remove(GTK_CONTAINER(menu), child);
        }
        children = g_list_delete_link(children, children);
    }

    // 创建自定义菜单项
    GtkWidget* settings_item = gtk_menu_item_new_with_label("设置");
    GtkWidget* search_item = gtk_menu_item_new_with_label("搜索");
    GtkWidget* edit_item = gtk_menu_item_new_with_label("编辑");

    // 绑定点击事件（传递主窗口指针用于对话框父窗口）
    if (settings_item && search_item && edit_item) {
        g_signal_connect(settings_item, "activate", G_CALLBACK(on_button_config), user_data);
        g_signal_connect(search_item, "activate", G_CALLBACK(on_button_search), user_data);
        g_signal_connect(edit_item, "activate", G_CALLBACK(on_button_edit), user_data);

        // 将菜单项添加到菜单
        //TODO gtk_menu_shell_append(GTK_MENU_SHELL(menu), settings_item);
        gtk_menu_shell_append(GTK_MENU_SHELL(menu), search_item);
        //TODO gtk_menu_shell_append(GTK_MENU_SHELL(menu), edit_item);

        // 显示所有菜单项
        gtk_widget_show_all(GTK_WIDGET(menu));
    } else {
        lyric_log_error("on_populate_popup: failed to create menu items");
    }
}

gpointer loading_lyrics(gpointer data)
{
    SetLyricsUIData* loading_data = (SetLyricsUIData*)data;
    g_assert(loading_data != NULL);
    g_assert(loading_data->widget != NULL);
    
    LyricWidget* lyric_widget = loading_data->widget;
    gint song_seq = loading_data->song_seq;

    lyric_log_info("loading_lyrics ...");

    // 检查location是否有效（使用传递的副本，而不是从widget读取）
    if (loading_data->location[0] == '\0') {
        lyric_log_warning("loading_lyrics: location is NULL, calling init_lyric_handle directly");
        // g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, (GSourceFunc)init_lyric_handle, loading_data, NULL);
        return NULL;
    }

    // 使用 GLib 函数获取歌词文件路径
    gchar* trackstring = get_lrc_path(loading_data->location, ".lrc");
    if (!trackstring) {
        lyric_log_error("load_lyrics: failed to get lrc path");
        // 释放加载数据
        free_set_lyrics_ui_data(loading_data);
        return NULL;
    }

    gchar* lyric_txt = NULL;
    
    // 尝试从文件读取歌词
    lyric_txt = read_from_file(trackstring);
    if (lyric_txt) {
        lyric_log_info("load_lyrics ...");
    }
    else {
        lyric_log_info("down_lyrics ...");
        // 从加载数据中读取artist和title（使用传递的副本，而不是从widget读取）
        const char* artist = loading_data->artist[0] != '\0' ? loading_data->artist : NULL;
        const char* title = loading_data->title[0] != '\0' ? loading_data->title : NULL;
        
        // 检查artist和title是否有效
        if (artist && title) {
            lyric_log_info("downloading lyrics for artist: %s, title: %s", artist, title);
            lyric_txt = kugou_down_lyrics(artist, title);
            lyric_log_info("down_lyrics completed, text length: %zu", lyric_txt ? strlen(lyric_txt) : 0);
            
            if (lyric_txt && strlen(lyric_txt) > 10) {
                lyric_log_info("saving lyrics to file: %s", trackstring);
                write_to_file(trackstring, lyric_txt);
                lyric_log_info("lyrics saved successfully");
            } else {
                lyric_log_warning("downloaded lyrics text is too short (length: %zu)", lyric_txt ? strlen(lyric_txt) : 0);
            }
        } else {
            lyric_log_warning("artist or title is NULL, skipping download");
        }
    }
    
    // 统一处理空歌词的情况（跨平台）
    if (!lyric_txt || strlen(lyric_txt) == 0) {
        lyric_log_warning("lyric_txt is empty after loading/downloading");
        // 不设置默认歌词，让程序继续运行但显示空歌词
        // 这样可以避免用户看到错误的"加载失败"信息，而是显示空状态
    }
    
    lyric_log_info("lyric text length: %zu", lyric_txt ? strlen(lyric_txt) : 0);
    if (lyric_txt && strlen(lyric_txt) > 0) {
        gchar* preview = g_strndup(lyric_txt, MIN(100, strlen(lyric_txt)));
        lyric_log_debug("lyric content preview: %s", preview);
        g_free(preview);
    }
    
    // 安全地调用 parse_lyrics（确保不为 NULL）
    GList* lyrics = NULL;
    if (lyric_txt && strlen(lyric_txt) > 0) {
        lyric_log_info("parse_lyrics ...");
        lyrics = parse_lyrics(lyric_txt);
        lyric_log_info("parse_lyrics end, lyrics count: %d", g_list_length(lyrics));
    } else {
        lyric_log_warning("parse_lyrics: skipping, lyric_txt is NULL or empty");
        lyrics = NULL;
    }
    
    // 清理内存
    g_free(lyric_txt);
    g_free(trackstring);
    
    // 检查是否已经切歌（通过比较计数器）
    guint current_sequence = get_current_sequence();
    
    if (song_seq != current_sequence) {
        lyric_log_warning("loading_lyrics: song changed (saved=%u, current=%u), discarding lyrics", 
                         song_seq, current_sequence);
        // 已经切歌，丢弃歌词
        if (lyrics) {
            free_lyrics_list(lyrics);
        }
        // 释放加载数据
        free_set_lyrics_ui_data(loading_data);
        return NULL;
    }
    
    // 将歌词存储在SetLyricsUIData中，而不是LyricWidget中
    loading_data->lyrics_temp = lyrics; // 不使用copy_lines(lyrics);
    
    lyric_log_info("loading_lyrics: saved sequence=%u, lyrics_temp count=%d", 
                   song_seq, lyrics ? g_list_length(lyrics) : 0);
    lyric_log_info("goto init_lyric_handle ...");
    // 使用较低优先级调度init_lyric_handle，确保set_lyrics_loading先执行
    // G_PRIORITY_DEFAULT_IDLE (200) 比 G_PRIORITY_DEFAULT (0) 优先级低
    guint timeout_id = g_timeout_add_full(G_PRIORITY_DEFAULT_IDLE, 0, (GSourceFunc)init_lyric_handle, loading_data, NULL);
    
    if (timeout_id != 0) {
        lyric_log_info("init_lyric_handle scheduled via g_timeout_add, timeout_id=%u", timeout_id);
    } else {
        lyric_log_warning("g_timeout_add failed, trying g_idle_add");
        
        // 后备方案：使用 g_idle_add_full 并指定较低优先级
        guint idle_id = g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, (GSourceFunc)init_lyric_handle, loading_data, NULL);
        if (idle_id == 0) {
            lyric_log_error("both g_timeout_add and g_idle_add failed!");
            lyric_log_error("init_lyric_handle could not be scheduled - lyrics may not display");
            // 释放加载数据
            free_set_lyrics_ui_data(loading_data);
        } else {
            lyric_log_info("init_lyric_handle scheduled via g_idle_add, idle_id=%u", idle_id);
        }
    }
    
    // 尝试唤醒主上下文（如果可能）
#ifdef _WIN32
    // 注意：这需要在主线程的主上下文中调用，但尝试也无妨
    GMainContext* main_context = g_main_context_default();
    if (main_context) {
        g_main_context_wakeup(main_context);
        lyric_log_debug("main context woken up");
    }
#endif
    
    lyric_log_info("loading_lyrics completed");
    // 注意：location副本会在 init_lyric_handle 中释放
    return NULL;
}

// UI线程回调函数：在主线程中执行UI更新操作
static gboolean set_lyrics_loading(gpointer user_data) {
	SetLyricsUIData* data = static_cast<SetLyricsUIData*>(user_data);
	g_assert(data != NULL);
	g_assert(data->widget != NULL);
	
	LyricWidget* widget = data->widget;
	
	g_assert(widget->lyric_buffer != NULL);

	// 先停止定时器并清理状态（clear_widget中的g_source_remove需要在主线程）
	// 注意：clear_widget会释放widget->title/artist/location，所以我们需要在之后重新设置
	clear_widget(widget);
	
	// 重新设置widget的数据（因为clear_widget已经清理了）
	g_mutex_lock(&widget->mutex);
	g_strlcpy(widget->title, data->title, sizeof(widget->title));
	g_strlcpy(widget->artist, data->artist, sizeof(widget->artist));
	g_strlcpy(widget->location, data->location, sizeof(widget->location));
	// 重置状态
	widget->current_line = -1;
	widget->past_line = NULL;
	g_mutex_unlock(&widget->mutex);
	
	// // 等待一小段时间，确保所有 GTK 操作完成
	// while (gtk_events_pending()) {
	// 	gtk_main_iteration();
	// }

	// 清空歌词面板
	GtkTextIter start, end;
	gtk_text_buffer_get_start_iter(widget->lyric_buffer, &start);
	gtk_text_buffer_get_end_iter(widget->lyric_buffer, &end);
	gtk_text_buffer_delete(widget->lyric_buffer, &start, &end);

	// 计算中间行位置
	gint above = gtk_text_view_get_pixels_above_lines(GTK_TEXT_VIEW(widget->lyric_view));
	gint below = gtk_text_view_get_pixels_below_lines(GTK_TEXT_VIEW(widget->lyric_view));
	int n = get_visible_line_count(GTK_TEXT_VIEW(widget->lyric_view), above, below);
	int middle_line = (int)round(n / 2.0f);

	// 插入空行使歌词居中
	GtkTextIter iter;
	gtk_text_buffer_get_end_iter(widget->lyric_buffer, &iter);
	for (int i = 0; i < middle_line - 1; i++) {
		gtk_text_buffer_insert_with_tags(widget->lyric_buffer, &iter, "\n", -1, tagCenter, NULL);
	}
	gtk_text_buffer_insert(widget->lyric_buffer, &iter, "\n", -1);

	// 插入标题和艺术家
	if (widget->title[0] != '\0') {
		gtk_text_buffer_insert_with_tags(widget->lyric_buffer, &iter, widget->title, -1, tagBold, tagLarge, tagCenter, NULL);
	}
	gtk_text_buffer_insert(widget->lyric_buffer, &iter, "\n", -1);
	if (widget->artist[0] != '\0') {
		gtk_text_buffer_insert_with_tags(widget->lyric_buffer, &iter, widget->artist, -1, tagBold, tagCenter, tagItalic, NULL);
	}
	gtk_text_buffer_insert(widget->lyric_buffer, &iter, "\n", -1);
	gtk_text_buffer_insert(widget->lyric_buffer, &iter, "\n", -1);

	// 显示加载中
	gtk_text_buffer_insert_with_tags(widget->lyric_buffer, &iter, "加载中...", -1, tagCenter, NULL);

	lyric_log_info("set_lyrics_loading completed");

	// 清理UI数据内存（注意：song_seq 不在这里释放，会在加载流程结束时释放）
	// g_free不再需要，因为我们现在使用的是字符数组而不是动态分配的字符串
	free_set_lyrics_ui_data(data);

	return G_SOURCE_REMOVE;
}

// UI线程回调函数：在主线程中执行失败状态设置
static gboolean set_lyric_failed(gpointer user_data) {
	SetLyricsUIData* data = static_cast<SetLyricsUIData*>(user_data);
	g_assert(data != NULL);
	g_assert(data->widget != NULL);
	
	LyricWidget* widget = data->widget;
	
	g_assert(widget->lyric_buffer != NULL);

	// 先停止定时器并清理状态（clear_widget中的g_source_remove需要在主线程）
	clear_widget(widget);
	
	// 重新设置widget的数据（因为clear_widget已经清理了）
	g_mutex_lock(&widget->mutex);
	// 从location获取文件名并设置显示（去掉后缀）
	if (data->location[0] != '\0') {
		// 获取文件名（去掉路径）
		gchar* filename = g_path_get_basename(data->location);
		// 去掉文件后缀
		gchar* dot = g_strrstr(filename, ".");
		if (dot) {
			*dot = '\0';
		}
		g_strlcpy(widget->title, "无法加载歌词", sizeof(widget->title));
		g_strlcpy(widget->artist, filename, sizeof(widget->artist));
		g_strlcpy(widget->location, data->location, sizeof(widget->location));
		g_free(filename);
	} else {
		g_strlcpy(widget->title, "无法加载歌词", sizeof(widget->title));
		g_strlcpy(widget->artist, "未知歌曲", sizeof(widget->artist));
		widget->location[0] = '\0';
	}
	// 重置状态
	widget->current_line = -1;
	widget->past_line = NULL;
	g_mutex_unlock(&widget->mutex);

	// 等待一小段时间，确保所有 GTK 操作完成
	while (gtk_events_pending()) {
		gtk_main_iteration();
	}

	// 清空歌词面板
	GtkTextIter start, end;
	gtk_text_buffer_get_start_iter(widget->lyric_buffer, &start);
	gtk_text_buffer_get_end_iter(widget->lyric_buffer, &end);
	gtk_text_buffer_delete(widget->lyric_buffer, &start, &end);

	// 计算中间行位置
	gint above = gtk_text_view_get_pixels_above_lines(GTK_TEXT_VIEW(widget->lyric_view));
	gint below = gtk_text_view_get_pixels_below_lines(GTK_TEXT_VIEW(widget->lyric_view));
	int n = get_visible_line_count(GTK_TEXT_VIEW(widget->lyric_view), above, below);
	int middle_line = (int)round(n / 2.0f);

	// 插入空行使内容居中
	GtkTextIter iter;
	gtk_text_buffer_get_end_iter(widget->lyric_buffer, &iter);
	for (int i = 0; i < middle_line - 1; i++) {
		gtk_text_buffer_insert_with_tags(widget->lyric_buffer, &iter, "\n", -1, tagCenter, NULL);
	}
	gtk_text_buffer_insert(widget->lyric_buffer, &iter, "\n", -1);

	// 显示标题和文件名
	gtk_text_buffer_insert_with_tags(widget->lyric_buffer, &iter, "无法加载歌词", -1, tagBold, tagLarge, tagCenter, NULL);
	gtk_text_buffer_insert(widget->lyric_buffer, &iter, "\n", -1);
	
	if (data->location[0] != '\0') {
		// 获取文件名并显示（去掉后缀）
		gchar* filename = g_path_get_basename(data->location);
		// 去掉文件后缀
		gchar* dot = g_strrstr(filename, ".");
		if (dot) {
			*dot = '\0';
		}
		gtk_text_buffer_insert_with_tags(widget->lyric_buffer, &iter, filename, -1, tagBold, tagCenter, tagItalic, NULL);
		g_free(filename);
	} else {
		gtk_text_buffer_insert_with_tags(widget->lyric_buffer, &iter, "未知歌曲", -1, tagBold, tagCenter, tagItalic, NULL);
	}
	
	gtk_text_buffer_insert(widget->lyric_buffer, &iter, "\n", -1);
	gtk_text_buffer_insert(widget->lyric_buffer, &iter, "\n", -1);

	// 设置"无法加载歌词"提示
	gtk_text_buffer_insert_with_tags(widget->lyric_buffer, &iter, "歌曲信息不完整，无法加载歌词", -1, tagCenter, NULL);

	lyric_log_info("set_lyric_failed UI update completed");

	// 清理内存
	free_set_lyrics_ui_data(data);

	return G_SOURCE_REMOVE;
}

void set_lyrics(SetLyricsUIData* data)
{
    g_assert(data != NULL);
    g_assert(data->widget != NULL);

    LyricWidget* widget = data->widget;
    const gchar* title = data->title;
    const gchar* artist = data->artist;
    const gchar* location = data->location;
    gint song_seq = data->song_seq;

    lyric_log_info("set_lyrics");
    lyric_log_info("title: %s", title);
    lyric_log_info("artist: %s", artist);
    lyric_log_info("location: %s", location);
    lyric_log_info("song_sequence: %u", song_seq);

    // 检查歌曲信息是否完整，如果不完整则设置失败状态
    if (strlen(title) == 0 || strlen(artist) == 0 || strlen(location) == 0) {
        lyric_log_warning("set_lyrics: song info incomplete, setting failed state");
        
        // 创建失败状态UI更新数据
        SetLyricsUIData* failed_data = g_new0(SetLyricsUIData, 1);
        failed_data->widget = widget;
        g_strlcpy(failed_data->title, title, sizeof(failed_data->title));
        g_strlcpy(failed_data->artist, artist, sizeof(failed_data->artist));
        g_strlcpy(failed_data->location, location, sizeof(failed_data->location));
        failed_data->song_seq = song_seq;
        failed_data->lyrics_temp = NULL; // 初始化为NULL

        // 使用更高优先级调度set_lyric_failed，确保它在init_lyric_handle之前执行
        // G_PRIORITY_HIGH (-100) 比 G_PRIORITY_DEFAULT (0) 优先级高
        guint source_id = g_timeout_add_full(G_PRIORITY_HIGH, 0, set_lyric_failed, failed_data, NULL);
        if (!source_id) {
            lyric_log_error("set_lyrics: failed to schedule failed state UI update to main thread");
            // 如果调度失败，清理内存
            free_set_lyrics_ui_data(failed_data);
            return;
        }

        lyric_log_debug("set_lyrics: failed state UI update scheduled to main thread, source_id=%u", source_id);
        return;
    }

    // 注意：数据更新会在UI线程的clear_widget之后进行，这里只准备UI数据
    // 不在后台线程中更新widget数据，因为clear_widget会清理它们

    // 创建UI更新数据，复制字符串（因为会在UI线程中使用）
    SetLyricsUIData* ui_data = g_new0(SetLyricsUIData, 1);
    ui_data->widget = widget;
    g_strlcpy(ui_data->title, title, sizeof(ui_data->title));
    g_strlcpy(ui_data->artist, artist, sizeof(ui_data->artist));
    g_strlcpy(ui_data->location, location, sizeof(ui_data->location));
    ui_data->song_seq = song_seq;
    ui_data->lyrics_temp = NULL; // 初始化为NULL

    // 使用更高优先级调度set_lyrics_loading，确保它在init_lyric_handle之前执行
    // G_PRIORITY_HIGH (-100) 比 G_PRIORITY_DEFAULT (0) 优先级高
    guint source_id = g_timeout_add_full(G_PRIORITY_HIGH, 0, set_lyrics_loading, ui_data, NULL);
    if (!source_id) {
        lyric_log_error("set_lyrics: failed to schedule UI update to main thread");
        // 如果调度失败，清理内存
        free_set_lyrics_ui_data(ui_data);
        return;
    }

    lyric_log_debug("set_lyrics: UI update scheduled to main thread, source_id=%u", source_id);
    
    // 创建加载线程数据，传递序列号和location副本
    SetLyricsUIData* loading_data = g_new0(SetLyricsUIData, 1);
    loading_data->widget = widget;
    g_strlcpy(loading_data->title, title, sizeof(loading_data->title));
    g_strlcpy(loading_data->artist, artist, sizeof(loading_data->artist));
    g_strlcpy(loading_data->location, location, sizeof(loading_data->location));
    loading_data->song_seq = song_seq;
    loading_data->lyrics_temp = NULL; // 初始化为NULL
    
    // 启动歌词加载线程（在任何线程中都可以）
     GThread *thr = g_thread_new("lyric_thread", loading_lyrics, loading_data);
     if(thr) {
        lyric_log_debug("set_lyrics: loading_lyrics thread started");
        g_thread_unref(thr);            
     } else {
        lyric_log_error("set_lyrics: failed to start loading_lyrics thread");
     }
}

gboolean lyric_timer_callback(gpointer user_data) {
    LyricWidget* widget = (LyricWidget*)user_data;

    if (widget->get_position) {
        float pos = widget->get_position(widget);
        update_lyrics(widget, pos);
    }
    return TRUE;
}

void start_time(LyricWidget* widget) {
    if (widget->timer_id != 0) {
        g_source_remove(widget->timer_id);
        widget->timer_id = 0;
    }
    widget->timer_id = g_timeout_add(300, lyric_timer_callback, widget);
}
